package tool

import cats.data.Validated
import implicits.Implicits._
import play.api.i18n.Messages

/**
 * Created by yz on 12/3/2020
 */

class GroupFileValidTool(lines: List[List[String]])(implicit messages: Messages) {

  val headers = lines.head
  val fileInfo = messages("groupFile")

  def validHeadersRepeat = {
    val repeatHeaders = headers.diffIgnoreCase(headers.distinct)
    val valid = repeatHeaders.isEmpty
    Validated.cond(valid, true, s"${messages("headerRepeat", fileInfo, repeatHeaders.head)}")
  }

  def validColumnNum = {
    val info = lines.drop(1).zipWithIndex.map { case (tmpColumns, i) =>
      val columns = tmpColumns
      val innerValid = columns.size <= headers.size && columns.size >= 2
      val inMessage = if (!innerValid) {
        s"${messages("columnNumValidOrLess2", fileInfo, i + 2)}"
      } else ""
      (innerValid, inMessage)
    }
    val valid = info.forall(_._1)
    val outMessages = info.map(_._2).notEmptyLines
    Validated.cond(valid, true, outMessages.head)
  }

  def validColumnsRepeat = {
    val repeatColumns = List("sample")
    val info = repeatColumns.map { header =>
      val totalColumns = lines.selectOneColumn(header)
      val repeatValues = totalColumns.diff(totalColumns.distinct)
      val inValid = repeatValues.isEmpty
      val inMessage = if (!inValid) {
        val repeatValue = repeatValues.head
        val j = headers.toLowerCase.indexOf(header)
        val i = totalColumns.lastIndexOf(repeatValue)
        s"${messages("columnRepeat", fileInfo, i + 2, j + 1)}"
      } else ""
      (inValid, inMessage)
    }
    val valid = info.forall(_._1)
    val outMessages = info.map(_._2)
    Validated.cond(valid, true, outMessages.head)
  }

  def validColumnValid = {
    val repeatColumns = List("classnote")
    val info = repeatColumns.map { header =>
      val totalColumns = lines.selectOneColumn(header)
      val noValidRVarHeaders = totalColumns.filterNot(_.isValidRVar)
      val inValid = noValidRVarHeaders.isEmpty
      val inMessage = if (!inValid) {
        val repeatValue = noValidRVarHeaders.head
        val j = header
        val i = totalColumns.lastIndexOf(repeatValue)
        s"${messages("groupNameFormatError", i+2, j + 1)}"
      } else ""
      (inValid, inMessage)
    }
    val valid = info.forall(_._1)
    val outMessages = info.map(_._2)
    Validated.cond(valid, true, outMessages.head)
  }

  def validHeadersExist = {
    val hasHeaders = List("sample", "classnote")
    val noExistHeaders = hasHeaders.diff(headers.toLowerCase)
    val valid = noExistHeaders.isEmpty
    Validated.cond(valid, true,s"${messages("headerNoExist", fileInfo, noExistHeaders.head)}")
  }

  def validGroupNum = {
    val repeatColumns = List("classnote")
    val info = repeatColumns.map { header =>
      val totalColumns = lines.selectOneColumn(header)
      val valid = totalColumns.toSet.size > 1
      val inMessage = if (!valid) {
        val j = headers.indexOfIgnoreCase(header)
        s"${messages("groupNumError", 2, j + 1)}"
      } else ""
      (valid, inMessage)
    }
    val valid = info.forall(_._1)
    val outMessages = info.map(_._2)
    Validated.cond(valid, true, outMessages.head)
  }
}

object GroupFileValidTool {

  def valid(lines: List[List[String]])(implicit messages: Messages) = {
    val fileValidTool = new GroupFileValidTool(lines)
    import fileValidTool._
    validHeadersRepeat.andThen { b =>
      validHeadersExist
    }.andThen { b =>
      validColumnNum
    }.andThen { b =>
      validColumnsRepeat
    }.andThen { b =>
      validColumnsRepeat
    }.andThen { b =>
      validGroupNum
    }.leftMap { x =>
      s"${messages("incorrectFormat")}!\n${x}"
    }

  }

  def validHeaders(lines: List[List[String]])(implicit messages: Messages) = {
    val fileValidTool = new GroupFileValidTool(lines)
    import fileValidTool._
    validHeadersRepeat.andThen { b =>
      validColumnNum
    }.leftMap { x =>
      s"${messages("incorrectFormat")}!\n${x}"
    }

  }


}
